package br.uff.probabilidade.modelo;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Vector;

public class Conjunto {	
	public static final int COORDENADAS_POR_LINHA = 4; //Quantidade de par ordenados em uma linha de impressao do conjunto
	private static final int ALTURA_LINHA = 17; //Altura (height) de uma linha da impressao
	
	private Vector paresOrdenados = new Vector();	
	private Point posicao;
	
	
	private char nome='L';
	
	public Conjunto(char nome, Point posicao){
		this.nome = nome;
		this.posicao = posicao;
	}		
	
	public Conjunto(char nome){
		this.nome = nome;
		this.posicao = new Point(0,0);
	}
	
	public Conjunto(){
		this.nome = ' ';
		this.posicao = new Point(0,0);
	}
	
	public void setNome(char nome){
		this.nome = nome;
	}
	
	private void insereParAt(int index,ParOrdenado par){
		ParOrdenado add = par,tmp;
		//for(int i=index;i<this.numerosPares();i++){
			//tmp = this.getParAt(i);
			this.paresOrdenados.add(index, add);
			//add = tmp;
		//}
		//this.paresOrdenados.add(add);
	}
	
	public void addParOrdenado(ParOrdenado par){
		if(this.numerosPares()==0){
			this.paresOrdenados.add(par);
		}else{
			System.out.println("Inserindo ...");
			int inicio = 0;
			int fim = this.numerosPares();
			int meio, compare;
			boolean sair = false;
			while(!sair){				
				meio = (inicio+fim)/2;
				System.out.println(inicio+" - "+fim+" -> "+meio);
				compare = this.getParAt(meio).compara(par); 
				if(compare>0){//Elemento eh menor
					if(meio-1>=0){
						if(this.getParAt(meio-1).compara(par)<0){						
							this.insereParAt(meio,par);
							sair=true;
						}else
							fim = meio;
					}else{
						this.insereParAt(0,par);
						sair=true;
					}
				}else if(compare<0){
					if(meio+1<this.numerosPares()){					
						if(this.getParAt(meio+1).compara(par)>0){
							this.insereParAt(meio,par);
							sair=true;						
						}else
							inicio = meio;
					}else{
						this.insereParAt(this.numerosPares(),par);
						sair=true;
					}
						
				}else
					sair=true;
			}
		}
	}
	
	public void addParOrdenado(Point coordenadas,Color colorX,Color colorY){
		this.addParOrdenado(new ParOrdenado(coordenadas,colorX,colorY));
	}
	
	public void removeParOrdenado(ParOrdenado parOrdenado){
		this.paresOrdenados.remove(parOrdenado);
	}
	
	public void removeParOrdenado(Point point){
		for(int i=0;i<this.numerosPares();i++){
			if(this.getParAt(i).getCoordenadas().x == point.x && this.getParAt(i).getCoordenadas().y == point.y){
				this.removeParOrdenado(this.getParAt(i));
			}
		}
	}
	
	public void desenha(Graphics g){	
		int tamanhoColuna = 35;
		System.out.println("Desenhando COnjunto");
		int space = 0;
		g.drawString(this.nome+" = {", this.posicao.x, this.posicao.y);
		
		space +=(this.nome+" = {").length()*7;
		Color oldColor = g.getColor();
		int numLinha = 0;
		int numCol = 0;
		for(int i=0;i<this.paresOrdenados.size();i++){			
			
			if(getParAt(i).isMostrandoErro())g.setColor(ParOrdenado.COLOR_WRONG_CHECK);
			
			g.drawString("(", this.posicao.x+space+tamanhoColuna*numCol, this.posicao.y+(numLinha*ALTURA_LINHA));
			
			
			if(!getParAt(i).isMostrandoErro())g.setColor(getParAt(i).getColorX());
			g.drawString(String.valueOf(getParAt(i).getCoordenadas().x+1), this.posicao.x+space+tamanhoColuna*numCol+5, this.posicao.y+(numLinha*ALTURA_LINHA));
			if(!getParAt(i).isMostrandoErro())g.setColor(oldColor);
			
			g.drawString(",", this.posicao.x+space+tamanhoColuna*numCol+7+String.valueOf(getParAt(i).getCoordenadas().x).length()*6, this.posicao.y+(numLinha*ALTURA_LINHA));
			
			
			if(!getParAt(i).isMostrandoErro())g.setColor(getParAt(i).getColorY());
			g.drawString(String.valueOf(getParAt(i).getCoordenadas().y+1), this.posicao.x+space+tamanhoColuna*numCol+10+String.valueOf(getParAt(i).getCoordenadas().x).length()*6, this.posicao.y+(numLinha*ALTURA_LINHA));
			if(!getParAt(i).isMostrandoErro())g.setColor(oldColor);
			
			g.drawString(")", this.posicao.x+space+tamanhoColuna*numCol+13+String.valueOf(getParAt(i).getCoordenadas().x).length()*6 +String.valueOf(getParAt(i).getCoordenadas().y).length()*6 , this.posicao.y+(numLinha*ALTURA_LINHA));
			
			//space+=getParAt(i).formatCoordenadas().length()*7;
			if(i+1<this.numerosPares())g.drawString(",", this.posicao.x+space+tamanhoColuna*(numCol+1) -5, this.posicao.y+(numLinha*ALTURA_LINHA));
			g.setColor(oldColor);
			numCol++;
			if(numCol % COORDENADAS_POR_LINHA ==0 && i+1 < this.numerosPares()){
				numCol = 0;
				numLinha ++;
			}
		}
		
		g.drawString("}",this.posicao.x+space+tamanhoColuna*numCol,this.posicao.y+(numLinha*ALTURA_LINHA));
	}
	
	
	public String getStringOfPares(){
		String pares = "";
		for(int i=0;i<this.paresOrdenados.size();i++){
			pares+=getParAt(i).formatCoordenadas();
			if(i+1<this.paresOrdenados.size())pares+=",";
		}
		return pares;
	}
	
	public ParOrdenado getParAt(int index){
		return (ParOrdenado)this.paresOrdenados.get(index);
	}
	
	public ParOrdenado getParByValue(int x, int y){		
		for(int i=0;i<numerosPares();i++){
			if(getParAt(i).getCoordenadas().x == x && getParAt(i).getCoordenadas().y == y){
				return getParAt(i);
			}
		}
		return null;
	}
	
	public ParOrdenado getParByValue(Point coordenadas){
		return this.getParByValue(coordenadas.x, coordenadas.y);
	}
	
	public int numerosPares(){
		return this.paresOrdenados.size();
	}

	public char getNome() {
		return nome;
	}

	public void moveTo(int x, int y){
		this.posicao.x = x;
		this.posicao.y = y;
	}

	public Point getPosicao() {
		return posicao;
	}

	public void setPosicao(Point posicao) {
		this.posicao = posicao;
	}
	
	public void limpa(){
		this.paresOrdenados.removeAllElements();
	}
	
	public int getFimImpressao(){
		//Retorna a posicao Y da ultima linha que foi necessaria para imprimir o conjunto completo;		
		return this.posicao.y + ALTURA_LINHA*((int)Math.ceil(((numerosPares())/(COORDENADAS_POR_LINHA)))+1);
	}
	
	public boolean hasParOrdenado(ParOrdenado par){
		for(int i=0;i<this.numerosPares();i++){
			if(this.getParAt(i).getCoordenadas().x == par.getCoordenadas().x && 
					this.getParAt(i).getCoordenadas().y == par.getCoordenadas().y)
				return true;
		}
		return false;
	}
	
	public int setMostrandoErro(){
		int qntErros = 0;
		for(int i=0;i<this.numerosPares();i++){
			if(!this.getParAt(i).isAceito()){
				qntErros++;
				this.getParAt(i).setMostrandoErro(true);
			}
		}
		return qntErros;
	}
	
	public int contaErro(){
		int qntErros = 0;
		for(int i=0;i<this.numerosPares();i++){
			if(!this.getParAt(i).isAceito()){
				qntErros++;				
			}
		}
		return qntErros;
	}
	
	public boolean hasCoordenada(Point coordenada){
		for(int i=0;i<this.numerosPares();i++){
			if(this.getParAt(i).getCoordenadas().x == coordenada.x && 
					this.getParAt(i).getCoordenadas().y == coordenada.y)
				return true;
		}
		return false;
	}
	
}
